package com.zmn.plat.business.impl.pilot;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceLogBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.manager.dictionary.OnePriceDict;
import com.zmn.plat.model.entity.area.BaseArea;
import com.zmn.plat.model.entity.pilot.ChannelPrice;
import com.zmn.plat.model.entity.pilot.ChannelPriceCity;
import com.zmn.plat.model.entity.pilot.ChannelPriceLog;
import com.zmn.plat.model.entity.pilot.ChannelPriceVO;
import com.zmn.plat.services.interfaces.area.BaseAreaService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: 渠道试点日志基础接口类
 *
 * @author yangshuangping
 * @since 2021-6-28 10:03:44
 */
@Slf4j
@Service
public class ChannelPriceLogBServiceImpl implements ChannelPriceLogBService {
    @Resource
    protected BaseAreaService baseAreaService;

    @Resource
    protected ChannelPriceLogService channelPriceLogService;


    @Override
    public void addChannelOnePriceLog(List<ChannelPriceCity> oldPriceCity, ChannelPrice oldChannelPrice, ChannelPrice newChannelPrice, String updater, Integer updaterId,
                                      ChannelPriceVO channelPriceVo) throws Exception {
        // 更新日志关联id
        ChannelPrice map = BeanMapper.map(newChannelPrice, ChannelPrice.class);

        ChannelPriceLog log = new ChannelPriceLog();
        // 字段更改转换
        Map<String, String> compare = this.compare(oldChannelPrice, map);
        StringBuilder stringBuilder = new StringBuilder();
        new ArrayList<>(compare.values()).forEach(e -> stringBuilder.append(e).append(GlobalConsts.HTML_LF));

        if (!compare.isEmpty()) {
            String s = this.formatterPriceCityChange(oldPriceCity, oldChannelPrice.getChannelPriceId(), channelPriceVo);
            stringBuilder.append(s);
            log.setContent(stringBuilder.toString());
            log.setAbutmenterType(3);
            log.setRelationId(newChannelPrice.getChannelPriceId());
            log.setCreateTime(DateUtil.getNow());
            log.setAbutmenter(updater);
            log.setAbutmenterId(updaterId);
            channelPriceLogService.insert(log);
        }
    }

    /**
     * 描述: 格式化城市配置操作日志
     *
     * @param oldPriceCity      旧的渠道执行城市配置
     * @param oldChannelPriceId 配置id
     * @param channelPriceVo    新对象
     * @return java.lang.String
     * @author yangshuangping
     * @since 2021-6-28 13:36:04
     **/
    private String formatterPriceCityChange(List<ChannelPriceCity> oldPriceCity, Integer oldChannelPriceId, ChannelPriceVO channelPriceVo) {

        StringBuilder sb = new StringBuilder();
        // 确认该城市配置数据为新增
        if (Objects.isNull(oldChannelPriceId)) {
            this.appendPriceCity(sb, oldChannelPriceId, channelPriceVo);
        } else {
            // 确认该城市配置数据为修改
            this.modifyPriceCity(oldPriceCity, sb, oldChannelPriceId, channelPriceVo);
        }

        log.info("# pilotChannel-saveTheLog-logContents# content:[{}]", sb);
        return sb.toString();
    }

    /**
     * 描述: 确认该城市配置数据为新增 日志收集
     *
     * @param sb                日志描述字符串
     * @param oldChannelPriceId 配置id
     * @param channelPriceVo    新对象
     * @author yangshuangping
     * @since 2021-6-28 13:36:04
     **/
    private void appendPriceCity(StringBuilder sb, Integer oldChannelPriceId, ChannelPriceVO channelPriceVo) {
        // 收集执行城市保存
        List<ChannelPriceCity> onePrice = this.collectPriceCities(channelPriceVo.getChannelPriceCityId(), oldChannelPriceId
                , "", OnePriceConsts.SUPPORT_CITY);
        if (!CollectionUtils.isEmpty(onePrice)) {
            sb.append("新增执行城市：");
            onePrice.forEach(e -> theDataPriceCity(sb, e));
            sb.append(GlobalConsts.HTML_LF);
        }
        // 收集不执行城市保存
        onePrice = this.collectPriceCities(channelPriceVo.getChannelBaseCityId(), oldChannelPriceId
                , "", OnePriceConsts.NOT_SUPPORT_CITY);
        if (!CollectionUtils.isEmpty(onePrice)) {
            sb.append("新增不执行城市：");
            onePrice.forEach(e -> theDataPriceCity(sb, e));
        }
    }


    /**
     * 描述: 格式化操作日志
     *
     * @param oldPriceCity      旧的配置数据
     * @param sb                日志记录容器
     * @param oldChannelPriceId 旧的配置id
     * @param channelPriceVo    新的数据
     * @author yangshuangping
     * @since 2021-6-28 13:36:04
     **/
    private void modifyPriceCity(List<ChannelPriceCity> oldPriceCity, StringBuilder sb, Integer oldChannelPriceId
            , ChannelPriceVO channelPriceVo) {

        // 页面传入的执行配置数据
        List<ChannelPriceCity> newPriceCity = this.collectPriceCities(channelPriceVo.getChannelPriceCityId()
                , oldChannelPriceId, GlobalConsts.SPLITER_EMPTY, OnePriceConsts.SUPPORT_CITY);
        String edit = this.formatterModifyPriceCityStr(oldPriceCity, newPriceCity, OnePriceConsts.SUPPORT_CITY);
        sb.append("编辑执行城市：").append(StringUtil.isNotBlank(edit) ? edit : GlobalConsts.SPLITER_EMPTY).append(GlobalConsts.HTML_LF);

        // 页面传入的不执行配置数据
        List<ChannelPriceCity> newBasePriceCity = this.collectPriceCities(channelPriceVo.getChannelBaseCityId()
                , oldChannelPriceId, GlobalConsts.SPLITER_EMPTY, OnePriceConsts.NOT_SUPPORT_CITY);
        edit = this.formatterModifyPriceCityStr(oldPriceCity, newBasePriceCity, OnePriceConsts.NOT_SUPPORT_CITY);
        sb.append("编辑不执行城市：").append(StringUtil.isNotBlank(edit) ? edit : "").append(GlobalConsts.HTML_LF);
    }

    /**
     * 描述: 格式化新旧数据记录日志
     *
     * @param oldPriceCity  旧的数据
     * @param newPriceCity  新的数据
     * @param operationType 操作类型
     * @return java.lang.String
     * @author yangshuangping
     * @since 2021-6-28 13:36:04
     **/
    private String formatterModifyPriceCityStr(List<ChannelPriceCity> oldPriceCity, List<ChannelPriceCity> newPriceCity
            , Integer operationType) {
        StringBuilder builder = new StringBuilder();
        StringBuilder newbuilder = new StringBuilder();
        // 旧的数据
        oldPriceCity.stream().filter(x -> Objects.equals(x.getType(), operationType)).forEach(e -> theDataBuilder(builder, e));
        // 新的数据
        newPriceCity.forEach(e -> theDataBuilder(newbuilder, e));

        if (Objects.equals(builder.toString(), newbuilder.toString())) {
            return GlobalConsts.SPLITER_EMPTY;
        }
        String newSbStr = StringUtil.isBlank(newbuilder.toString()) ? "\"无\"" : newbuilder.toString();
        String oldSbStr = StringUtil.isBlank(builder.toString()) ? "\"无\"" : builder.toString();
        return oldSbStr + "变更为" + newSbStr;

    }


    /**
     * 描述: 收集城市执行 or 执行标准城市价
     *
     * @param channelCityIdStr 城市执行 or 执行标准城市价数据
     * @param channelPriceId   渠道执行id
     * @param updater          数据修改人
     * @return java.util.List<com.zmn.plat.model.entity.oneprice.ChannelPriceCity>
     * @author yangshuangping
     * @since 2021-6-28 13:36:04
     **/
    @Override
    public List<ChannelPriceCity> collectPriceCities(String channelCityIdStr, Integer channelPriceId, String updater
            , Integer operationType) {

        if (StringUtil.isBlank(channelCityIdStr)) {
            return Collections.emptyList();
        }
        Map<Integer, String> areaMap = this.formatterAreaStrToList(channelCityIdStr);

        return Optional.of(Arrays.asList(channelCityIdStr.split(GlobalConsts.SPLITER_DEFAULT)))
                .orElse(Collections.emptyList()).stream()
                .map(mm -> {

                    List<String> stringList = Arrays.asList(mm.split(OnePriceConsts.SPLITER_DOLLAR_SIGN));

                    if (stringList.size() >= GlobalConsts.NO) {
                        ChannelPriceCity channelPriceCity = new ChannelPriceCity();
                        channelPriceCity.setChannelPriceId(channelPriceId);
                        int provinceId = Integer.parseInt(stringList.get(GlobalConsts.NONE));
                        channelPriceCity.setProvinceId(provinceId);
                        channelPriceCity.setProvinceName(areaMap.get(provinceId));

                        if (stringList.size() == GlobalConsts.YES) {
                            int cityId = Integer.parseInt(stringList.get(GlobalConsts.NO));
                            channelPriceCity.setCityId(cityId);
                            channelPriceCity.setCityName(areaMap.get(cityId));
                        }
                        channelPriceCity.setType(operationType);
                        channelPriceCity.setCreater(updater);
                        channelPriceCity.setCreateTime(DateUtil.getNow());
                        return channelPriceCity;
                    }
                    return null;
                }).collect(Collectors.toList());
    }

    /**
     * 描述: 格式化翻译城市信息数据
     *
     * @param str 执行城市str or 不执行城市
     * @return java.util.Map<java.lang.Integer, java.lang.String>
     * @author yangshuangping
     * @since 2021-6-28 11:21:20
     **/
    private Map<Integer, String> formatterAreaStrToList(String str) {
        // 将字符串转为list
        ArrayList<Integer> ids = Lists.newArrayList();

        Optional.of(Arrays.asList(str.split(GlobalConsts.SPLITER_DEFAULT)))
                .orElse(Collections.emptyList()).stream()
                .map(e -> Arrays.asList(e.split(OnePriceConsts.SPLITER_DOLLAR_SIGN)))
                .distinct()
                .forEach(list -> {
                    List<Integer> collect = list.stream()
                            .map(Integer::parseInt)
                            .distinct()
                            .collect(Collectors.toList());
                    ids.addAll(collect);
                });
        // 根据ids 获取区域数据
        return Optional.ofNullable(baseAreaService.findByKeys(ids))
                .orElse(Collections.emptyList()).stream()
                .collect(Collectors.toMap(BaseArea::getAreaId, BaseArea::getName));
    }

    /**
     * 描述: 检查2个对象间不同
     *
     * @param obj1 对象1
     * @param obj2 对象2
     * @return java.util.Map<java.lang.String>
     * @author yangshuangping
     * @since 2021-6-28 11:21:20
     **/
    private <T> Map<String, String> compare(T obj1, T obj2) throws Exception {
        Map<String, String> result = Maps.newHashMap();
        List<Field> list = Lists.newArrayList(obj1.getClass().getDeclaredFields());
        for (Field field : list) {
            field.setAccessible(true);
            Object v1 = field.get(obj1);
            Object v2 = field.get(obj2);
            if (!this.equals(v1, v2)) {
                String operation = Objects.isNull(v1) ? "新增" : "编辑";
                String change = "新增".equals(operation) ? "" : "变更为";
                switch (field.getName()) {
                    case "payType":
                        result.put("payType", MessageFormat.format("{0} 支付方式：{1}{2}{3}"
                                , operation, OnePriceDict.getPayType(toInteger(v1)), change, OnePriceDict.getPayType(toInteger(v2))));
                        break;
                    case "priceDiscount":
                        result.put("priceDiscount", MessageFormat.format("{0} 执行优惠: {1}{2}{3}"
                                , operation, OnePriceDict.getPriceDiscount(toInteger(v1)), change, OnePriceDict.getPriceDiscount(toInteger(v2))));
                        break;
                    case "status":
                        result.put("status", MessageFormat.format("{0} 状态：{1}{2}{3}"
                                , operation, OnePriceDict.getStatus(toInteger(v1)), change, OnePriceDict.getStatus(toInteger(v2))));
                        break;
                    default:
                        break;
                }
            }
        }
        return result;
    }

    /**
     * 数据生成器
     *
     * @param builder 原有字符串
     * @param city    渠道试点执行城市
     * @author yangshuangping
     * @since 2021-6-28 11:21:20
     */
    private void theDataBuilder(StringBuilder builder, ChannelPriceCity city) {
        if (StringUtil.isNotBlank(city.getCityName())) {
            builder.append("\"").append(city.getProvinceName()).append(city.getCityName()).append("\"");
        } else {
            builder.append("\"").append(city.getProvinceName()).append("\"");
        }
        builder.append(",");
    }

    /**
     * 转换渠道试点日志内容
     *
     * @param builder
     * @param city
     * @author yangshuangping
     * @since 2021-6-28 11:21:20
     */
    private void theDataPriceCity(StringBuilder builder, ChannelPriceCity city) {

        builder.append(Optional.ofNullable(city.getProvinceName()).orElse(GlobalConsts.SPLITER_EMPTY))
                .append(Optional.ofNullable(city.getCityName()).orElse(GlobalConsts.SPLITER_EMPTY))
                .append("、");
    }

    /**
     * 类型转换
     *
     * @param obj obj
     * @return Integer
     * @author yangshuangping
     * @since 2021-6-28 10:48:40
     */
    public Integer toInteger(Object obj) {
        return Integer.parseInt(Optional.ofNullable(obj).orElse("0").toString());
    }

    /**
     * 描述: 对比
     *
     * @param original 对象1
     * @param target   对象2
     * @return boolean
     * @author yangshuangping
     * @since 2021-6-28 10:48:40
     **/
    private boolean equals(Object original, Object target) {
        return original == target ? true : (original == null || target == null ? false : original.equals(target));
    }
}

